package com.basic.ui.list

import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.annotation.ColorInt
import androidx.recyclerview.R
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager

/**
 * @author Peter Liu
 * @since 2023/8/10 14:13
 *
 */
open class CommonRecycleView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = R.attr.recyclerViewStyle
) : RecyclerView(context, attrs, defStyleAttr) {

    protected val baseAdapter by lazy { BaseAdapter() }

    fun linear(
        @RecyclerView.Orientation orientation: Int = VERTICAL,
        reverseLayout: Boolean = false,
        stackFromEnd: Boolean = false
    ): CommonRecycleView {
        layoutManager = LinearLayoutManager(context, orientation, reverseLayout).apply {
            this.stackFromEnd = stackFromEnd
        }
        return this
    }

    fun vertical(
        reverseLayout: Boolean = false,
        stackFromEnd: Boolean = false
    ): CommonRecycleView {
        return linear(VERTICAL)
    }

    fun horizontal(
        reverseLayout: Boolean = false,
        stackFromEnd: Boolean = false
    ): CommonRecycleView {
        return linear(HORIZONTAL)
    }

    fun grid(
        spanCount: Int = 1,
        @RecyclerView.Orientation orientation: Int = VERTICAL,
        reverseLayout: Boolean = false,
    ): CommonRecycleView {
        val grid = GridLayoutManager(context, spanCount, orientation, reverseLayout)
        grid.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int): Int {
                val spanSize = baseAdapter.getItemTypeBinder(position)?.getSpanSize() ?: -1
                return if (spanSize < 0) {
                    spanCount
                } else {
                    spanSize
                }
            }
        }
        layoutManager = grid
        return this
    }

    fun staggeredGrid(
        spanCount: Int,
        @RecyclerView.Orientation orientation: Int = VERTICAL,
        reverseLayout: Boolean = false,
    ): RecyclerView {
        val staggeredGrid = StaggeredGridLayoutManager(spanCount, orientation).apply {
            this.reverseLayout = reverseLayout
        }
        layoutManager = staggeredGrid
        return this
    }

    fun divider(width: Int, @ColorInt color: Int): CommonRecycleView {
        addItemDecoration(DividerItemDecoration(width, color))
        return this
    }

    fun divider(block: DividerItemDecoration.() -> Unit): CommonRecycleView {
        addItemDecoration(DividerItemDecoration(block))
        return this
    }

    //<editor-fold desc="内部支持BaseAdapter">

    fun <DATA> setItemType(
        layoutId: Int,
        spanSize: Int = -1,
        binder: ItemUpdater<BaseHolder, DATA>
    ): CommonRecycleView {
        baseAdapter.addItemType(ItemLayoutBinder(layoutId, spanSize, binder))
        return this
    }

    //设置条目
    fun <VH : BaseHolder, DATA> setItemType(typeItemType: ItemTypeBinder<DATA, VH>): CommonRecycleView {
        baseAdapter.addItemType(typeItemType)
        return this
    }

    fun <VH : BaseHolder, DATA> addItemType(typeItemType: ItemTypeBinder<DATA, VH>): CommonRecycleView {
        baseAdapter.addItemType(typeItemType)
        return this
    }

    fun <VH : BaseHolder, DATA> addItemType(
        type: Int,
        typeItemType: ItemTypeBinder<DATA, VH>
    ): CommonRecycleView {
        baseAdapter.addItemType(type, typeItemType)
        return this
    }

    fun <VH : BaseHolder, DATA> addItemType(
        clazz: Class<DATA>,
        typeItemType: ItemTypeBinder<DATA, VH>
    ): CommonRecycleView {
        baseAdapter.addItemType(clazz, typeItemType)
        return this
    }

    fun setFooter(layoutId: Int, binder: (BaseHolder.() -> Unit)? = null): CommonRecycleView {
        baseAdapter.setFooter(layoutId, binder)
        return this
    }

    fun setFooter(view: View): CommonRecycleView {
        baseAdapter.setFooter(view)
        return this
    }

    fun showFooter(show: Boolean): CommonRecycleView {
        baseAdapter.showFooter = show
        return this
    }

    fun setHeader(layoutId: Int, binder: (BaseHolder.() -> Unit)? = null): CommonRecycleView {
        baseAdapter.setHeader(layoutId, binder)
        return this
    }

    fun setHeader(view: View): CommonRecycleView {
        baseAdapter.setHeader(view)
        return this
    }

    fun showHeader(show: Boolean): CommonRecycleView {
        baseAdapter.showHeader = show
        return this
    }

    //</editor-fold>

    fun setOnItemClickListener(itemClick: (holder: BaseHolder, data: Any) -> Unit): CommonRecycleView {
        baseAdapter.onItemClickListener = object : OnItemClickListener {
            override fun onItemClick(holder: BaseHolder, data: Any) {
                itemClick.invoke(holder, data)
            }
        }
        return this
    }

    fun setOnItemLongClickListener(itemLongClick: (holder: BaseHolder, data: Any) -> Boolean): CommonRecycleView {
        baseAdapter.onItemLongClickListener = object : OnItemLongClickListener {
            override fun onItemLongClick(holder: BaseHolder, data: Any): Boolean {
                return itemLongClick.invoke(holder, data)
            }
        }
        return this
    }

    fun setOnItemChildClickListener(onItemChildClick: (view: View?, holder: BaseHolder, data: Any) -> Unit): CommonRecycleView {
        baseAdapter.onItemChildClickListener = object : OnItemChildClickListener {
            override fun onItemChildClick(view: View?, holder: BaseHolder, data: Any) {
                onItemChildClick(view, holder, data)
            }
        }
        return this
    }

    fun setOnItemChildLongClickListener(onItemChildLongClick: (view: View?, holder: BaseHolder, data: Any) -> Boolean): CommonRecycleView {
        baseAdapter.onItemChildLongClickListener = object : OnItemChildLongClickListener {
            override fun onItemChildLongClick(view: View?, holder: BaseHolder, data: Any): Boolean {
                return onItemChildLongClick(view, holder, data)
            }
        }
        return this
    }
}